--[[协程api的基本使用
    (1)coroutine.running ()
　　    用来判断当前执行的协程是不是主线程，如果是，就返回true。
    (2)coroutine.status (co)
    　　返回一个字符串，表示协程的状态。有4种状态：
    　　1）、running。如果在协程的函数中调用status，传入协程自身的句柄，那么执行到这里的时候才会返回running状态。
    　　2）、suspended。如果协程还未结束，即自身调用了yeild或还没开始运行，那么就是suspended状态。
    　　3）、normal。如果协程Aresume协程B时，协程A处于的状态为normal。在协程B的执行过程中，协程A就一直处于normal状态。
        因为它这时候既不是挂起状态、也不是运行状态。
    　　4）、dead。如果一个协程发生错误结束，或正常终止。那么就处于dead状态。如果这时候对它调用resume，将返回false和错误消息。
    (3)coroutine.wrap (f)
    　　wrap()也是用来创建协程的。只不过这个协程的句柄是隐藏的。跟create()的区别在于：
    　　1）、wrap()返回的是一个函数，每次调用这个函数相当于调用coroutine.resume()。
    　　2）、调用这个函数相当于在执行resume()函数。
    　　3）、调用这个函数时传入的参数，就相当于在调用resume时传入的除协程的句柄外的其他参数。
    　　4）、调用这个函数时，跟resume不同的是，它并不是在保护模式下执行的，若执行崩溃会直接向外抛出。
    (4)coroutine.resume (co [, val1, ···])
    　　用来启动或再次启动一个协程，使其由挂起状态变成运行状态。
    　　可以这么说，resume函数相当于在执行协程中的方法。参数Val1...是执行协程co时传递给协程的方法。
    　　首次执行协程co时，参数Val1...会传递给协程co的函数；
    　　再次执行协程co时，参数Val1...会作为给协程co中上一次yeild的返回值。
    　　resume函数返回什么呢？有3种情况：
    　　1）、如果协程co的函数执行完毕，协程正常终止，resume 返回 true和函数的返回值。
    　　2）、如果协程co的函数执行过程中，协程让出了（调用了yeild()方法），那么resume返回true和协程中调用yeild传入的参数。
    　　3）、如果协程co的函数执行过程中发生错误，resume返回false与错误消息。
    　　可以看到resume无论如何都不会导致程序崩溃。它是在保护模式下执行的
    (5)coroutine.yield (···)
    　　使正在执行的函数挂起。
    　　传递给yeild的参数会作为resume的额外返回值。
    　  同时，如果对该协程不是第一次执行resume，resume函数传入的参数将会作为yield的返回值。
]]
function foo (a)
    print("foo", a)
    return coroutine.yield(2 * a) --会作为resume的返回值
end

--first-class
co = coroutine.create(function (a,b) --1 10
    print("co-body1", a, b) --co-body 1 10  打印参数
    local r = foo(a + 1) --foo     2 --打印参数
    print("co-body2", r) --main    true    4 --打印yield的返回值
    local r, s = coroutine.yield(a + b, a - b)
    print("co-body3", r, s)
    return b, "end"
end)

print("main", coroutine.resume(co, 1, 10))
print("main", coroutine.resume(co, "r"))
print("main", coroutine.resume(co, "x", "y"))
print("main", coroutine.resume(co, "x", "y"))
--[[
    co-body 1       10   --打印参数 print("main", coroutine.resume(co, 1, 10)) 开始
    foo     2  --打印函数内部参数
    main    true    4 --函数内部yield的返回值，正常结束，返回true和返回值  print("main", coroutine.resume(co, 1, 10)) 结束

    co-body r   --执行第二个resume,打印参数 print("main", coroutine.resume(co, "r")) 开始
    main    true    11      -9  正常结束，返回true和返回值(传递给yeild的参数会作为resume的额外返回值。) print("main", coroutine.resume(co, "r")) 结束
    co-body x       y   --执行第二个resume,打印参数, print("main", coroutine.resume(co, "x", "y")) 开始
    main    true    10      end
    main    false   cannot resume dead coroutine  --已经yield是dead
]]

--[[
    co-body1        1       10
    foo     2
    main    true    4
    co-body2        r
    main    true    11      -9
    co-body3        x       y
    main    true    10      end --协程直接返回，再resume无效
    main    false   cannot resume dead coroutine
]]